using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.WebControls;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.Reflection;

namespace UserControlHostingWebPartSolution
{
    [Guid("ed3e0acc-e13e-4545-9184-e7a5af415a28")]
    public class UserControlHostingWebPart : Microsoft.SharePoint.WebPartPages.WebPart
    {
        private Control _hostedcontrol;
        private Dictionary<string, string> _PropertyValuesCollection = new Dictionary<string, string>();

        public Control hostedcontrol
        {
            get
            {
                EnsureChildControls();
                return _hostedcontrol;
            }
        }

        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [System.ComponentModel.Category("UserControl")]
        [WebDisplayName("UserControl URL")]
        [WebDescription("The URL referencing the UserControl to be hosted")]
        public string UserControlUrl
        {
            get;
            set;
        }

        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(false)]
        public string UserControlType
        {
            get;
            set;
        }
        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(false)]
        public string PropertyValues
        {
            get
            {
                XmlDocument doc = new XmlDocument();
                XmlNode nodeProperties = doc.AppendChild(doc.CreateElement("Properties"));
                foreach (KeyValuePair<string, string> property in PropertyValuesCollection)
                {
                    XmlNode nodeProperty = nodeProperties.AppendChild(doc.CreateElement("Property"));
                    XmlAttribute attrPropertyName = nodeProperty.Attributes.Append(doc.CreateAttribute("Name"));
                    attrPropertyName.Value = property.Key;
                    nodeProperty.InnerText = property.Value;
                }
                return doc.OuterXml;
            }
            set
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(value);
                PropertyValuesCollection.Clear();
                foreach (XmlNode node in doc.SelectNodes("Properties/Property"))
                {
                    string key = node.Attributes["Name"].Value;
                    string val = node.InnerText;
                    PropertyValuesCollection.Add(key, val);
                }
            }
        }

        public Dictionary<string, string> PropertyValuesCollection
        {
            get
            {
                return _PropertyValuesCollection;
            }
        }


        public UserControlHostingWebPart()
        {
            this.ExportMode = WebPartExportMode.All;
        }

        /// <summary>
        /// Create all your controls here for rendering.
        /// Try to avoid using the RenderWebPart() method.
        /// </summary>
        protected override void CreateChildControls()
        {
            if (!string.IsNullOrEmpty(UserControlUrl))
            {
                try
                {
                    _hostedcontrol = Page.LoadControl(UserControlUrl);
                    foreach (KeyValuePair<string, string> property in PropertyValuesCollection)
                    {
                        try
                        {
                            Type hostedcontroltype = hostedcontrol.GetType();                            
                            PropertyInfo pi = hostedcontroltype.GetProperty(property.Key);
                            object val = Convert.ChangeType(property.Value, pi.PropertyType);
                            pi.SetValue(hostedcontrol, val, null);
                        }
                        catch
                        {
                        }
                    }
                    Controls.Add(hostedcontrol);
                }
                catch (Exception ex)
                {
                    Label lbl = new Label();
                    lbl.Text = ex.ToString();
                    Controls.Add(lbl);
                }
            }
        }

        public override EditorPartCollection CreateEditorParts()
        {
            UserControlHostingParametersEditorPart uchpep = new UserControlHostingParametersEditorPart();
            return new EditorPartCollection(base.CreateEditorParts(), new object[] { uchpep });
        }

    }
}
